package com.yb.guigu.pick.auth.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yb.guigu.pick.auth.bean.dto.request.SysRouteAddInfo;
import com.yb.guigu.pick.auth.bean.dto.response.SysRouteDTO;
import com.yb.guigu.pick.auth.bean.vo.request.RouteCreateRequest;
import com.yb.guigu.pick.auth.entity.SysRole;
import com.yb.guigu.pick.auth.entity.SysRoleRoute;
import com.yb.guigu.pick.auth.entity.SysRoute;
import com.yb.guigu.pick.auth.mapper.SysRouteMapper;
import com.yb.guigu.pick.auth.mapper.SysUserMapper;
import com.yb.guigu.pick.auth.service.*;
import com.yb.guigu.pick.security.bean.GuiguPickUser;
import com.yb.guigu.pick.security.util.SecurityUtil;
import com.yb.guigu.pick.core.bean.GuiguResult;
import com.yb.guigu.pick.core.constant.RouteConstant;
import com.yb.guigu.pick.core.publisher.GuiguPickEventPublisher;
import com.yb.guigu.pick.core.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 姚兵
 * @since 2023-06-04
 */
@Service
@Slf4j
public class SysRouteServiceImpl extends ServiceImpl<SysRouteMapper, SysRoute> implements ISysRouteService {

    @Autowired
    ISysPermissionService sysPermissionService;

    @Autowired
    ISysRoleService sysRoleService;

    @Autowired
    ISysRoleRouteService sysRoleRouteService;


    @Autowired
    ISysUserRoleService userRoleService;


    @Autowired
    GuiguPickEventPublisher guiguPickEventPublisher;

    @Autowired
    SysUserMapper sysUserMapper;
    @Override
    public GuiguResult routeAll() {
        List<SysRoute> routes = this.list();
        List<SysRouteDTO> sysRouteDTOS=new ArrayList<>(routes.size());
        routes.forEach(route -> {
            SysRouteDTO sysRouteDTO = new SysRouteDTO();
            BeanUtils.copyProperties(route,sysRouteDTO);
            sysRouteDTOS.add(sysRouteDTO);
        });

        //封装dto对象到 children里面
        return GuiguResult.success(treeify(sysRouteDTOS));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public GuiguResult create(RouteCreateRequest routeCreateRequest) {
        SysRoute sysRoute=new SysRoute();

        BeanUtils.copyProperties(routeCreateRequest,sysRoute);

        Integer sort = routeCreateRequest.getSort();
        if(Objects.isNull(sort)){
            sysRoute.setSort(0);
        }


        //如果是顶级菜单
        if(Objects.isNull(routeCreateRequest.getLevel())){
            sysRoute.setLevel(1);
            sysRoute.setParentId(0);

        }



        sysRoute.setIsLeaf(RouteConstant.IsLeaf.YES.getValue());

        sysRoute.setIsMenuLeaf(RouteConstant.IsLeaf.YES.getValue());
        //创建路由
        this.save(sysRoute);


        //更新当前路由的routeIdpath
        String routeIdPath;
        if(sysRoute.getParentId()!=0){
            SysRoute parentRoute=this.getById(sysRoute.getParentId());
            routeIdPath = parentRoute.getRouteIdPath();
            routeIdPath = StringUtil.join(routeIdPath,sysRoute.getId());

        }else{
            routeIdPath=String.valueOf(sysRoute.getId());
        }

        SysRoute updateCurrent = new SysRoute();
        updateCurrent.setId(sysRoute.getId());
        sysRoute.setRouteIdPath(routeIdPath);
        updateCurrent.setRouteIdPath(routeIdPath);
        this.updateById(updateCurrent);



        //父级路由设置为非叶子节点，当前路由设置为叶子节点

        SysRoute parentUpdate=new SysRoute();

        parentUpdate.setId(sysRoute.getParentId());

        Integer isMenu = routeCreateRequest.getIsMenu();

        parentUpdate.setIsLeaf(RouteConstant.IsLeaf.NO.getValue());

        //如果当前添加的是子菜单，则将父节点置为非叶子节点
        if(RouteConstant.IsMenu.YES.getValue().equals(isMenu)){
            parentUpdate.setIsMenuLeaf(RouteConstant.IsMenu.NO.getValue());
        }


        this.updateById(parentUpdate);
        //创建权限
        routeCreateRequest.getPermission().setRouteId(sysRoute.getId());
        routeCreateRequest.getPermission().setRouteIdPath(sysRoute.getRouteIdPath());
        sysPermissionService.create(routeCreateRequest.getPermission());

        guiguPickEventPublisher.publish(this,new SysRouteAddInfo(sysRoute));

        return GuiguResult.success();

    }

    @Override
    public GuiguResult listAll() {

        return GuiguResult.success(this.list());
    }


    @Override
    public GuiguResult queryLevelList(Integer parentId,boolean queryMenu){

        LambdaQueryWrapper<SysRoute> queryWrapper = new LambdaQueryWrapper<SysRoute>().eq(SysRoute::getParentId, parentId);


        if(parentId==0&&queryMenu){
            //如果是查询菜单,查询根节点
            queryWrapper.eq(SysRoute::getName,"root");
        }else if(queryMenu) {

            //如果不是查询根节点，但是查询菜单
            queryWrapper.eq(SysRoute::getIsMenu, RouteConstant.IsMenu.YES.getValue());
        }

        return GuiguResult.success(this.list(queryWrapper));
    }

    @Override
    public GuiguResult listForUser() {
        Authentication authentication = SecurityUtil.getAuthentication();
        Set<Integer> routeIds=new HashSet<>();
        if(authentication instanceof AnonymousAuthenticationToken){
            //当前用户是匿名用户,匿名用户只需要查询匿名用户的路由
            log.info("当前用户是匿名用户");
            SysRole anonymousRole = sysRoleService.getOne(new LambdaQueryWrapper<SysRole>().eq(SysRole::getRoleCode, "anonymous"));


            List<SysRoleRoute> list = sysRoleRouteService.list(new LambdaQueryWrapper<SysRoleRoute>()
                    .eq(SysRoleRoute::getRoleId, anonymousRole.getRoleId())
                    .select(SysRoleRoute::getRouteId));

            List<Integer> collect = list.stream().map(SysRoleRoute::getRouteId).collect(Collectors.toList());

            routeIds.addAll(collect);
        }else{
            GuiguPickUser userInfo = SecurityUtil.getUserInfo();
            log.info("当前用户是[{}]用户",userInfo.getUsername());

            //查询当前用户的路由信息

            Integer userId = userInfo.getUserId();
            List<Integer> userRouteIds = sysUserMapper.listRouteIds(userId);
            routeIds.addAll(userRouteIds);
        }


        //否则查询当前用户的角色列表

        log.info("authentication:{}",authentication);
        return GuiguResult.success(this.list(new LambdaQueryWrapper<SysRoute>().in(SysRoute::getId,routeIds)));
    }

    @Override
    public GuiguResult menus() {
        SysRoute rootRoute = this.getOne(new LambdaQueryWrapper<SysRoute>().eq(SysRoute::getName, "root"));
        List<SysRouteDTO> menus = this.baseMapper.menus();
        return GuiguResult.success(menus);
    }

    private List<SysRouteDTO>  treeify(List<SysRouteDTO> sysRouteDTOS){

        Map<Integer, List<SysRouteDTO>> parentIdMap = sysRouteDTOS.stream().filter(Objects::nonNull)
                .filter(item -> !item.getParentId().equals(0))
                .collect(Collectors.groupingBy(SysRouteDTO::getParentId));
        log.info("{}",parentIdMap);

        sysRouteDTOS.forEach(item->{
            List<SysRouteDTO> childList = parentIdMap.get(item.getId());
            if(Objects.nonNull(childList))
                item.setChildren(childList);
        });
        log.info("treeVos:{}",sysRouteDTOS);
        List<SysRouteDTO> collect = sysRouteDTOS.stream().filter(item -> item.getParentId().equals(0)).collect(Collectors.toList());
        log.info("collect:{}",collect);
        return collect;
    }

}
